package com.ting.mybatis.parse;

import com.ting.mybatis.exception.MyBuilderException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.InputStream;

/**
 * @Author: ting
 *
 * 构建XPath解析器、把xml文件解析为文档
 */

public class MyXPathParser {

    //JDK提供
    private XPath xPath;

    //文档对象:xml文件读取进来是个文档
    //JDK提供
    private Document document;

    public MyXPathParser(InputStream inputStream) {
        this.xPath=createXPath();
        this.document=createDocument(new InputSource(inputStream));

    }

    /**
     * 初始化XPath,里面方法JDK提供
     */

    public XPath createXPath(){
        XPathFactory factory=XPathFactory.newInstance();
        return factory.newXPath();
    }

    /**
     * 创建Document对象
     *
     * jdk自带dom解析
     * 这里是jdk代码
     *
     * 把xml解析成文档
     * */

    private Document createDocument(InputSource inputSource) {
        // important: this must only be called AFTER common constructor
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);


            factory.setNamespaceAware(false);
            factory.setIgnoringComments(true);
            factory.setIgnoringElementContentWhitespace(false);
            factory.setCoalescing(false);
            factory.setExpandEntityReferences(true);

            DocumentBuilder builder = factory.newDocumentBuilder();

            builder.setErrorHandler(new ErrorHandler() {
                @Override
                public void error(SAXParseException exception) throws SAXException {
                    throw exception;
                }

                @Override
                public void fatalError(SAXParseException exception) throws SAXException {
                    throw exception;
                }

                @Override
                public void warning(SAXParseException exception) throws SAXException {
                    // NOP
                }
            });
            return builder.parse(inputSource);
        } catch (Exception e) {
            throw new MyBuilderException("Error creating document instance.  Cause: " + e, e);
        }
    }


    /**
     * 根据一个xpath表达式解析一个xml节点
     * */
    public Node xNode(String expression){

        Node node=null;

        //JDK代码
        try {
            node=(Node)xPath.evaluate(expression,document, XPathConstants.NODE);
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return node;
    }




    public XPath getxPath() {
        return xPath;
    }

    public void setxPath(XPath xPath) {
        this.xPath = xPath;
    }

    public Document getDocument() {
        return document;
    }

    public void setDocument(Document document) {
        this.document = document;
    }
}
